import axios, {
  type AxiosInstance,
  type InternalAxiosRequestConfig,
  type AxiosResponse,
} from 'axios'
import { ElMessage } from 'element-plus'
import config from '../config/index'
import type { ApiResponse } from '../types/api'

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: config.API_BASE_URL,
  timeout: 30000,
  withCredentials: true, // 启用cookie凭证以确保会话一致性
})

// 存储正在进行的请求
const pendingRequests = new Map<string, AbortController>()

// 生成请求唯一标识
function generateRequestKey(config: InternalAxiosRequestConfig): string {
  const { method, url, params, data } = config
  // 包含请求参数和请求体的请求标识，确保不同参数的相同URL请求不会被视为重复请求
  // 这解决了在案件详情页面加载多个请求时出现的"API No Response"错误
  const paramsString = params ? JSON.stringify(params) : ''
  const dataString = data ? JSON.stringify(data) : ''
  return `${method || 'GET'}-${url || ''}-${paramsString}-${dataString}`
}

// 重置userInfo请求状态的函数
export function resetUserInfoRequest(): void {
  // 清除所有与userInfo相关的请求
  for (const [key, controller] of pendingRequests.entries()) {
    if (key.includes('/api/auth/userInfo')) {
      pendingRequests.delete(key)
    }
  }
}

// 全局重置所有请求状态
export function resetAllRequests(): void {
  for (const controller of pendingRequests.values()) {
    controller.abort()
  }
  pendingRequests.clear()
}

// 全局标记，用于防止重复显示登录过期提示
const isTokenExpired = false
const tokenExpiredTimer: NodeJS.Timeout | null = null

// 全局防抖函数
let lastUserInfoRequestTime = 0
const DEBOUNCE_TIME = 100 // 防抖时间，单位毫秒

// 检查是否需要防抖
function shouldDebounce(config: InternalAxiosRequestConfig): boolean {
  const isUserInfoRequest = config.url?.includes('/api/auth/userInfo')
  if (!isUserInfoRequest) return false

  const now = Date.now()
  const timeSinceLastRequest = now - lastUserInfoRequestTime

  if (timeSinceLastRequest < DEBOUNCE_TIME) {
    return true
  }

  lastUserInfoRequestTime = now
  return false
}

service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 处理OPTIONS预检请求
    if (config.method === 'options') {
      config.headers.set('Access-Control-Request-Method', 'GET, POST, PUT, DELETE')
      config.headers.set(
        'Access-Control-Request-Headers',
        'Origin, X-Requested-With, Content-Type, Accept, Authorization'
      )
    }

    // 优化验证码请求的跨域处理
    if (config.url && config.url.includes('captcha')) {
      // 确保不会因为缓存导致验证码不刷新
      config.headers.set('Cache-Control', 'no-cache, no-store, must-revalidate')
      config.headers.set('Pragma', 'no-cache')
      config.headers.set('Expires', '0')
    }

    // 添加JWT令牌
    const token = localStorage.getItem('token')
    const isLoginRoute = config.url && config.url.includes('/auth/login')
    const isCaptchaRoute = config.url && config.url.includes('captcha')

    if (token && !isLoginRoute && !isCaptchaRoute) {
      // 只使用标准的Authorization头，避免CORS问题
      config.headers.set('Authorization', `Bearer ${token}`)
    }

    // 防重复请求处理 - 生成请求唯一标识
    const requestKey = generateRequestKey(config)

    // 检查是否是userInfo请求并且需要防抖
    if (shouldDebounce(config)) {
      // 创建包含完整配置信息的错误对象
      return Promise.reject({
        ...new Error('Duplicate request - debounced'),
        code: 'ERR_CANCELED',
        config,
      })
    }

    // 检查是否有重复请求
    if (pendingRequests.has(requestKey)) {
      // 取消当前请求
      const controller = new AbortController()
      config.signal = controller.signal
      controller.abort('Duplicate request')
      // 创建包含完整配置信息的错误对象
      return Promise.reject({ ...new Error('Duplicate request'), code: 'ERR_CANCELED', config })
    }

    // 存储请求控制器（仅在非重复请求时执行）
    const controller = new AbortController()
    config.signal = controller.signal
    pendingRequests.set(requestKey, controller)

    return config
  },
  error => {
    // 记录请求配置错误
    console.error('API Request Config Error:', {
      error: error.message,
      timestamp: new Date().toISOString(),
    })
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  (response: AxiosResponse) => {
    // 移除已完成的请求
    const requestKey = generateRequestKey(response.config)
    pendingRequests.delete(requestKey)

    // 处理响应
    const headers = response.headers as any
    const contentType = headers.get ? headers.get('content-type') : headers['content-type']

    // 对于blob类型的响应直接返回
    if (response.config.responseType === 'blob') {
      return response
    }

    // 对于文本类型的响应，尝试解析为JSON
    if (contentType && contentType.includes('application/json')) {
      try {
        const res = response.data

        // 检查是否有code字段
        if (res && typeof res === 'object' && res.code !== undefined) {
          switch (res.code) {
            case 0:
              return res
            case 401:
              // 处理未授权错误
              localStorage.removeItem('token')
              resetUserInfoRequest()

              // 避免在登录页面重复提示
              if (!window.location.href.includes('/login')) {
                ElMessage({
                  message: '登录过期，需重新登录',
                  type: 'warning',
                  duration: 3000,
                  onClose: () => {
                    window.location.href = '/login'
                  },
                })
              }
              return Promise.reject(res)
            default:
              // 对于其他错误码，不是所有都需要reject，例如某些业务操作的特殊状态码
              // 如果msg存在，则显示错误消息，但仍返回响应数据
              if (res.msg && res.code !== 0) {
                // 对于菜单加载错误，避免重复提示
                const isMenuRequest = response.config.url && response.config.url.includes('/menu')
                if (!isMenuRequest) {
                  ElMessage.error(res.msg)
                }
              }
              return res
          }
        }
        return res
      } catch (error) {
        return response
      }
    }

    // 对于其他类型的响应，直接返回
    return response.data
  },
  error => {
    // 移除已完成的请求（包括失败的请求）
    if (error.config) {
      const requestKey = generateRequestKey(error.config)
      pendingRequests.delete(requestKey)
    }

    // 从错误信息中提取状态码（增强健壮性）
    let statusCode = error.response?.status
    // 如果没有response对象但error包含状态码信息
    if (!statusCode && error.message && /\b(\d{3})\b/.test(error.message)) {
      statusCode = parseInt(error.message.match(/\b(\d{3})\b/)![1])
    }

    // 增强的错误类型检测
    const isNetworkError =
      error.code === 'ERR_NETWORK' || (error.message && error.message.includes('CORS'))
    const is401Error = statusCode === 401 || error.response?.status === 401
    const is403Error = statusCode === 403 || error.response?.status === 403
    const is404Error = statusCode === 404 || error.response?.status === 404
    const isNoResponse = !error.response && !is401Error && !is403Error && !is404Error

    // 特别处理跨域错误
    if (isNetworkError) {
      console.error('API Network Error:', {
        url: error.config?.url,
        method: error.config?.method,
        status: statusCode || error.response?.status,
        statusText: error.response?.statusText,
        message: error.message || '未知错误',
        code: error.code,
        timestamp: new Date().toISOString(),
        details: '可能的原因: 服务器不可达、跨域配置问题、网络连接中断',
        baseURL: service.defaults.baseURL,
      })
      ElMessage({
        message: '网络连接异常或跨域问题，请检查API地址设置和服务器配置',
        type: 'error',
      })
    }
    // 其他错误处理
    else if (is401Error) {
      console.error('API Authentication Error:', {
        url: error.config?.url,
        method: error.config?.method,
        status: statusCode || error.response?.status,
        statusText: error.response?.statusText,
        message: error.message || '未知错误',
        code: error.code,
        timestamp: new Date().toISOString(),
        details: '认证失败，token可能已过期或无效',
      })
      localStorage.removeItem('token')
      resetUserInfoRequest()

      if (!window.location.href.includes('/login')) {
        ElMessage({
          message: '登录过期，需重新登录',
          type: 'warning',
          duration: 3000,
          onClose: () => {
            window.location.href = '/login'
          },
        })
      }
    } else if (is403Error) {
      console.error('API Authorization Error:', {
        url: error.config?.url,
        method: error.config?.method,
        status: statusCode || error.response?.status,
        statusText: error.response?.statusText,
        message: error.message || '未知错误',
        code: error.code,
        timestamp: new Date().toISOString(),
        details: '权限不足，用户没有访问该资源的权限',
      })
      ElMessage({
        message: '权限不足',
        type: 'error',
      })
    } else if (isNoResponse) {
      // 忽略所有被取消的请求，不显示错误消息
      if (error.code === 'ERR_CANCELED') {
        return Promise.reject(error)
      }

      console.error('API No Response:', {
        url: error.config?.url,
        method: error.config?.method,
        status: statusCode || error.response?.status,
        statusText: error.response?.statusText,
        message: error.message || '未知错误',
        code: error.code,
        timestamp: new Date().toISOString(),
        details: '服务器未响应，可能的原因: 服务器宕机、网络连接问题、防火墙阻止',
        additionalInfo: '如果这是认证相关的请求，请确认token是否有效',
      })
      // 处理网络错误，更友好的提示
      ElMessage({
        message: '网络连接异常，请检查网络设置',
        type: 'error',
      })
    } else {
      // 处理404错误（找不到资源）
      if (is404Error) {
        console.error('API Resource Not Found:', {
          url: error.config?.url,
          method: error.config?.method,
          status: statusCode || error.response?.status,
          statusText: error.response?.statusText,
          message: error.message || '未知错误',
          code: error.code,
          timestamp: new Date().toISOString(),
          details: '请求的资源不存在，请检查API路径是否正确',
        })
        ElMessage({
          message: `未找到请求的资源: ${error.config?.url || ''}`,
          type: 'error',
        })
      } else {
        // 处理其他HTTP错误
        console.error('API HTTP Error:', {
          url: error.config?.url,
          method: error.config?.method,
          status: statusCode || error.response?.status,
          statusText: error.response?.statusText,
          message: error.message || '未知错误',
          code: error.code,
          timestamp: new Date().toISOString(),
          details: 'HTTP请求失败',
        })
        const errorMsg = error.response.data?.msg || error.response.statusText || '请求处理失败'
        ElMessage({
          message: errorMsg,
          type: 'error',
        })
      }
    }
    return Promise.reject(error)
  }
)

// 定义request对象的接口
interface RequestInstance {
  // 原始请求函数
  (config: Partial<InternalAxiosRequestConfig> & { responseType: 'blob' }): Promise<AxiosResponse>
  (config: Partial<InternalAxiosRequestConfig>): Promise<ApiResponse<any>>

  // HTTP方法
  get<T = any>(
    url: string,
    params?: any,
    config?: Partial<InternalAxiosRequestConfig>
  ): Promise<ApiResponse<T>>
  post<T = any>(
    url: string,
    data?: any,
    config?: Partial<InternalAxiosRequestConfig>
  ): Promise<ApiResponse<T>>
  put<T = any>(
    url: string,
    data?: any,
    config?: Partial<InternalAxiosRequestConfig>
  ): Promise<ApiResponse<T>>
  delete<T = any>(
    url: string,
    params?: any,
    config?: Partial<InternalAxiosRequestConfig>
  ): Promise<ApiResponse<T>>

  // 验证码请求
  requestCaptcha: typeof requestCaptcha
}

// 创建基础请求函数
function baseRequest(
  config: Partial<InternalAxiosRequestConfig> & { responseType: 'blob' }
): Promise<AxiosResponse>
function baseRequest(config: Partial<InternalAxiosRequestConfig>): Promise<ApiResponse<any>>
function baseRequest(config: Partial<InternalAxiosRequestConfig>): Promise<any> {
  // 确保必需的headers字段存在
  const fullConfig: InternalAxiosRequestConfig = {
    ...config,
    headers: new axios.AxiosHeaders(config.headers || {}),
  }
  return service(fullConfig)
}

// 创建带有HTTP方法的request对象
const request = baseRequest as RequestInstance

// 添加HTTP方法
request.get = function <T = any>(
  url: string,
  params?: any,
  config?: Partial<InternalAxiosRequestConfig>
): Promise<ApiResponse<T>> {
  // 确保请求配置完整性
  return baseRequest({
    method: 'get',
    url,
    params,
    ...config,
  })
}

// 导出一个函数来重置userInfo请求状态（用于测试或特殊场景）
export const resetAllPendingRequests = () => {
  resetAllRequests()
}

request.post = function <T = any>(
  url: string,
  data?: any,
  config?: Partial<InternalAxiosRequestConfig>
): Promise<ApiResponse<T>> {
  return baseRequest({
    method: 'post',
    url,
    data,
    ...config,
  })
}

request.put = function <T = any>(
  url: string,
  data?: any,
  config?: Partial<InternalAxiosRequestConfig>
): Promise<ApiResponse<T>> {
  return baseRequest({
    method: 'put',
    url,
    data,
    ...config,
  })
}

request.delete = function <T = any>(
  url: string,
  params?: any,
  config?: Partial<InternalAxiosRequestConfig>
): Promise<ApiResponse<T>> {
  return baseRequest({
    method: 'delete',
    url,
    params,
    ...config,
  })
}

async function requestCaptcha(
  url: string = '/api/captcha',
  config: Partial<InternalAxiosRequestConfig> = {}
): Promise<AxiosResponse> {
  // 为了防止缓存，每次请求都添加时间戳
  const timestamp = Date.now()
  const urlWithTimestamp = url.includes('?') ? `${url}&t=${timestamp}` : `${url}?t=${timestamp}`

  // 确保使用正确的基础配置
  const defaultConfig: InternalAxiosRequestConfig = {
    url: urlWithTimestamp,
    method: 'get',
    responseType: 'blob',
    timeout: 15000, // 增加超时时间
    withCredentials: true, // 修复：验证码需要凭据以维持会话状态
    headers: new axios.AxiosHeaders({
      'Cache-Control': 'no-cache, no-store, must-revalidate',
      Pragma: 'no-cache',
      Expires: '0',
    }),
  }

  // 合并用户配置，但保持withCredentials为true
  const mergedConfig = {
    ...defaultConfig,
    ...config,
    withCredentials: true, // 强制设置为true，确保验证码能够正常工作
    headers: new axios.AxiosHeaders({
      ...defaultConfig.headers.toJSON(),
      ...((config?.headers as any)?.toJSON?.() || config?.headers || {}),
    }),
  }

  // 添加更详细的错误处理
  try {
    const response = await service(mergedConfig)

    // 确保返回的是Blob类型
    if (response.data instanceof Blob && response.data.size === 0) {
      throw new Error('验证码图片数据为空')
    }

    return response
  } catch (error) {
    // 提供更具体的错误信息
    const errorObj = error as any
    if (errorObj.code === 'ECONNABORTED') {
      throw new Error('验证码请求超时，请检查网络连接')
    } else if (errorObj.code === 'ECONNREFUSED') {
      throw new Error('无法连接到服务器，请确认后端服务已启动')
    } else if (errorObj.code === 'ERR_NETWORK') {
      console.error('网络错误，可能是CORS问题或API地址错误:', {
        baseURL: service.defaults.baseURL,
        fullUrl: `${service.defaults.baseURL}${urlWithTimestamp}`,
        error: errorObj,
      })
      throw new Error(`网络连接错误，请检查API地址设置: ${service.defaults.baseURL}`)
    } else if (errorObj.response) {
      console.error('服务器返回错误:', {
        status: errorObj.response.status,
        statusText: errorObj.response.statusText,
        data: errorObj.response.data,
      })
      throw new Error(`服务器错误: ${errorObj.response.status} ${errorObj.response.statusText}`)
    }

    throw error
  }
}

// 将requestCaptcha函数赋值给request对象
request.requestCaptcha = requestCaptcha

// 导出带有HTTP方法的request对象
export default request

export { requestCaptcha }
